package com.wx.generator.core;


import com.sun.xml.internal.ws.util.StringUtils;
import com.wx.generator.column.ColumnClass;
import com.wx.generator.config.CodeGenerateConfig;
import com.wx.generator.utils.FreeMarkerTemplateUtils;
import freemarker.template.Template;

import java.io.*;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.util.*;

/**
 * @author wx
 * @Description: 代码生成器
 * @date 2018/11/17 001716:34
 */
public class CodeGenerate {
    /**
     * 表名
     */
    private String tableName;
    /**
     * 描述
     */
    private String tableAnnotation;
    /**
     * 驼峰命名后的表名
     */
    private String changeTableName;

    public CodeGenerate(String tableName, String tableAnnotation) {
        this.tableName = tableName;
        this.tableAnnotation = tableAnnotation;
        String result = replaceUnderLineAndUpperCase(tableName);
        if (result.charAt(0) == 'T') {
            this.changeTableName = result.substring(1);
        } else {
            this.changeTableName = result;
        }


    }

    public Connection getConnection() throws Exception {
        Class.forName(CodeGenerateConfig.DRIVER);
        Connection connection = DriverManager.getConnection(CodeGenerateConfig.URL, CodeGenerateConfig.USER, CodeGenerateConfig.PASSWORD);
        return connection;
    }

    public void generate() throws Exception {
        try {
            Connection connection = getConnection();
            DatabaseMetaData databaseMetaData = connection.getMetaData();
            ResultSet resultSet = databaseMetaData.getColumns(null, "%", tableName, "%");
            List<ColumnClass> columnClassList = new ArrayList<ColumnClass>();
            while (resultSet.next()) {
                ColumnClass columnClass = new ColumnClass();
                //获取字段名称
                columnClass.setColumnName(resultSet.getString("COLUMN_NAME"));
                //获取字段类型
                columnClass.setColumnType(resultSet.getString("TYPE_NAME"));
                //转换字段名称，如 sys_name 变成 SysName
                columnClass.setChangeColumnName(replaceUnderLineAndUpperCase(resultSet.getString("COLUMN_NAME")));
                //字段在数据库的注释
                columnClass.setColumnComment(resultSet.getString("REMARKS"));
                columnClassList.add(columnClass);
            }
            //生成Mapper文件
            generateMapperFile(columnClassList);
            //生成Dao文件
            generateDaoFile();
            //生成服务层接口文件
            generateServiceFile();
            //生成Controller层文件
            generateControllerFile();
            //生成DTO文件
            generateDTOFile(columnClassList);
            //生成PO
            generatePOFile(columnClassList);
            //生成QO
            generateQOFile(columnClassList);
            //生成VO
            generateVOFile(columnClassList);

        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {

        }
    }


    /**
     * @param columnClassList
     * @description: 生成dto
     * @author: wx
     * @date: 2018/11/17 0017
     * @return: void
     */
    private void generateDTOFile(List<ColumnClass> columnClassList) throws Exception {
        final String suffix = "DTO.java";
        final String templateName = "Model.ftl";
        generateModelFile(columnClassList, suffix, templateName);
    }

    /**
     * @param columnClassList
     * @description: 生成qo
     * @author: wx
     * @date: 2018/11/17 0017
     * @return: void
     */
    private void generateQOFile(List<ColumnClass> columnClassList) throws Exception {
        final String suffix = "QO.java";
        final String templateName = "Model.ftl";
        generateModelFile(columnClassList, suffix, templateName);
    }

    /**
     * @param columnClassList
     * @description: 生成vo
     * @author: wx
     * @date: 2018/11/17 0017
     * @return: void
     */
    private void generateVOFile(List<ColumnClass> columnClassList) throws Exception {
        final String suffix = "VO.java";
        final String templateName = "Model.ftl";
        generateModelFile(columnClassList, suffix, templateName);
    }

    /**
     * @param columnClassList
     * @description: 生成po
     * @author: wx
     * @date: 2018/11/17 0017
     * @return: void
     */
    private void generatePOFile(List<ColumnClass> columnClassList) throws Exception {
        final String suffix = "PO.java";
        final String templateName = "Model.ftl";
        generateModelFile(columnClassList, suffix, templateName);
    }

    /**
     * @description: 生成Controller
     * @author: wx
     * @date: 2018/11/17 0017
     * @return: void
     */
    private void generateControllerFile() throws Exception {
        final String suffix = "Controller.java";
        final String templateName = "Controller.ftl";
        generateFile(suffix, templateName);
    }


    /**
     * @description: 生成Service
     * @author: wx
     * @date: 2018/11/17 0017
     * @return: void
     */
    private void generateServiceFile() throws Exception {
        final String suffix = "Service.java";
        final String templateName = "Service.ftl";
        generateFile(suffix, templateName);
    }

    /**
     * @description: 生成Dao
     * @author: wx
     * @date: 2018/11/17 0017
     * @return: void
     */
    private void generateDaoFile() throws Exception {
        final String suffix = "DAO.java";
        final String templateName = "DAO.ftl";
        generateFile(suffix, templateName);

    }

    /**
     * @description: 生成Mapper
     * @author: wx
     * @date: 2018/11/17 0017
     * @return: void
     */
    private void generateMapperFile(List<ColumnClass> columnClassList) throws Exception {
        final String suffix = "Mapper.xml";
        final String templateName = "Mappter.ftl";
        generateModelFile(columnClassList, suffix, templateName);

    }

    /**
     * @param suffix       后缀文件名
     * @param templateName 模板文件名
     * @description: 生成文件
     * @author: wx
     * @date: 2018/11/17 0017
     * @return: void
     */
    private void generateFile(String suffix, String templateName) throws Exception {
        String lowercaseSuffix = suffix.substring(0, suffix.lastIndexOf(".")).toLowerCase();
        final String path = CodeGenerateConfig.diskPath + lowercaseSuffix + "//" + changeTableName + suffix;
        File mapperFile = new File(path);
        Map<String, Object> dataMap = new HashMap<String, Object>();
        generateFileByTemplate(templateName, mapperFile, dataMap);
    }

    /**
     * @param templateName 模板名称
     * @param file         文件流
     * @param dataMap      输出数据
     * @description: 生成文件具体逻辑
     * @author: wx
     * @date: 2018/11/17 0017
     * @return: void
     */
    private void generateFileByTemplate(final String templateName, File file, Map<String, Object> dataMap) throws Exception {
        fileMkdir(file);
        Template template = FreeMarkerTemplateUtils.getTemplate(templateName);
        FileOutputStream fos = new FileOutputStream(file);
        dataMap.put("table_name_small", tableName);
        dataMap.put("table_name", changeTableName);
        dataMap.put("author", CodeGenerateConfig.AUTHOR);
        dataMap.put("date", CodeGenerateConfig.CURRENT_DATE);
        dataMap.put("package_name", CodeGenerateConfig.packageName);
        dataMap.put("table_annotation", tableAnnotation);
        dataMap.put("limit", "LIMIT #{startPosition} , #{pageSize}");
        Writer out = new BufferedWriter(new OutputStreamWriter(fos, "utf-8"), 10240);
        template.process(dataMap, out);
    }

    /**
     * @param columnClassList
     * @description: 生成实体文件
     * @author: wx
     * @date: 2018/11/17 0017
     * @return: void
     */
    private void generateModelFile(List<ColumnClass> columnClassList, String suffix, String templateName) throws Exception {
        String suffixname = suffix.substring(0, suffix.lastIndexOf("."));
        final String path = CodeGenerateConfig.diskPath + suffixname.toLowerCase() + "//" + changeTableName + suffix;
        File mapperFile = new File(path);
        Map<String, Object> dataMap = new HashMap<String, Object>();
        dataMap.put("model_column", columnClassList);
        dataMap.put("package_entity", suffixname.toLowerCase());
        dataMap.put("model_name", changeTableName + suffixname);
        generateFileByTemplate(templateName, mapperFile, dataMap);

    }

    /**
     * @param str
     * @description: 表名 驼峰命名
     * @author: wx
     * @date: 2018/11/19 0019
     * @return: java.lang.String
     */
    private String replaceUnderLineAndUpperCase(String str) {
        StringBuffer sb = new StringBuffer();
        sb.append(str);
        int count = sb.indexOf("_");
        while (count != 0) {
            int num = sb.indexOf("_", count);
            count = num + 1;
            if (num != -1) {
                char ss = sb.charAt(count);
                char ia = (char) (ss - 32);
                sb.replace(count, count + 1, ia + "");
            }
        }
        String result = sb.toString().replaceAll("_", "");
        return StringUtils.capitalize(result);
    }

    /**
     * @param file
     * @description: 验证路径是否存在，如果不存在则创建改文件夹
     * @author: wx
     * @date: 2018/11/20 0020
     * @return: void
     */
    private void fileMkdir(File file) {
        File fileParent = file.getParentFile();
        if (!fileParent.exists()) {
            fileParent.mkdirs();
        }
    }
}
